package org.fve.sip;


import java.security.*;
import java.util.Random;
import gov.nist.javax.sip.Utils;

public class DigestAuthentication {

    private String realm;
    private String userName;
    private String uri;
    private String nonce;
    private String password;
    private String method;
    private String cnonce;
    private String qop;
    private int requestCounter;
    private MessageDigest messageDigest;     


    public void initialize(String realm, String userName, String uri, String nonce,
    String password, String method, String algorithm,String qop,int requestCounter,String cnonce) throws Exception {
        if (qop==null) throw new Exception("The qop parameter is null");
            this.qop=qop;  
            this.requestCounter=requestCounter;    
        if (realm==null) throw new Exception("The realm parameter is null");
            this.realm=realm;
        if (userName==null) throw new Exception("The userName parameter is null");
            this.userName=userName;
        if (uri==null) throw new Exception("The uri parameter is null");
            this.uri=uri;
        if (nonce==null) throw new Exception("The nonce parameter is null");
            this.nonce=nonce;
        if (password==null) throw new Exception("The password parameter is null");
            this.password=password;
        if (method==null) throw new Exception("The method parameter is null");
            this.method=method;
            this.cnonce=cnonce; 
        if (algorithm==null) throw new Exception("The algorithm parameter is null");
            try {
            messageDigest = MessageDigest.getInstance(algorithm);
        }
        catch ( NoSuchAlgorithmException ex ) {
        System.out.println("DEBUG, DigestClientAuthenticationMethod, initialize(): "+
            "ERROR: Digest algorithm does not exist.");
            throw new Exception("ERROR: Digest algorithm does not exist.");
    }
    }

     /**
      * generate the response
      */
    public String generateResponse() {
     if (userName == null) {
            System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
            "ERROR: no userName parameter");
            return null;
         }
     if (realm == null) {
            System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
            "ERROR: no realm parameter");
            return  null;
         }

         System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
         "Trying to generate a response for the user: "+userName+" , with "+
         "the realm: "+ realm);

     if (password == null)  {
            System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
            "ERROR: no password parameter");
        return null;
         }
         if (method == null)  {
            System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
            "ERROR: no method parameter");
        return null;
         }
         if (uri== null)  {
            System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
            "ERROR: no uri parameter");
        return null;
         }
         if (nonce== null)  {
            System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
            "ERROR: no nonce parameter");
        return null;
         }
         if (messageDigest== null)  {
            System.out.println("DEBUG, DigestClientAuthenticationMethod, generateResponse(): "+
            "ERROR: the algorithm is not set");
        return null;
         }


         /*******    GENERATE RESPONSE      ************************************/
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), userName:"+userName+"!");
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), realm:"+realm+"!");
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), password:"+password+"!");
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), uri:"+uri+"!");
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), nonce:"+nonce+"!");
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), cnonce:"+cnonce+"!");
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), method:"+method+"!");
         // A1
         String A1 = userName + ":" + realm+ ":" +   password ;
         byte mdbytes[] = messageDigest.digest(A1.getBytes());
         String HA1 = Utils.toHexString(mdbytes);
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), HA1:"+HA1+"!");
         //A2
         String A2 = method.toUpperCase() + ":" + uri ;
         mdbytes = messageDigest.digest(A2.getBytes());
         String HA2 = Utils.toHexString(mdbytes);
         System.out.println("DigestClientAuthenticationMethod-->generateResponse(), HA2:"+HA2+"!");
         //KD
         String KD = HA1 + ":" + nonce;
         if (qop != null) {
         	KD += ":" + fve.Utils_.toHexString(requestCounter).substring(8);
             KD += ":" + cnonce;
             KD += ":" + qop;
             System.out.println("DigestClientAuthenticationMethod-->generateResponse(), qop:"+qop+"!");
             System.out.println("DigestClientAuthenticationMethod-->generateResponse(), nc:"+ fve.Utils_.toHexString(requestCounter)+"!");
         }
         KD += ":" + HA2;
         mdbytes = messageDigest.digest(KD.getBytes());
         String response = Utils.toHexString(mdbytes);

         System.out.println("DigestClientAuthenticationMethod-->generateResponse():"+
         " response generated: "+response);

         return response;
    }

      

}
